#include <windows.h>
#include <stdio.h>
#include "api.h"
#include "image.h"
#include "data.h"
#include "tools.h"
#include "toolwnd.h"
#include "colorswnd.h"
#include "panelwnd.h"
#include "filedlg.h"
#include "boardwnd.h"
#include "resource.h"

#define IMAGE_FILE_LOADER_FILTER "Imagen PNG (*.png)\0*.png\0Imagen Bitmap (*.bmp)\0*.bmp\0\0";
#define IMAGE_FILE_SAVER_FILTER "Imagen PNG (*.png)\0*.png\0\0";

#define szClassName "MINERVAMAINWND"

typedef struct _MAINWND_{
	HWND panelTool;
	HWND panelColores;
	HWND board;
	HBRUSH backgroundPanels;
	TOOL_CALLBACK currentTool;
} *PMAINWND, MAINWND;

PDATA data;

MAINWND mainWnd;

void mainWndOnCreate(HWND hwnd, PDATA data){
	if (!data->config->isMaximized){
		MoveWindow(hwnd, data->config->winpx, data->config->winpy, data->config->windx, data->config->windy, TRUE);
	}
	RECT rcClient;
	GetClientRect(hwnd, &rcClient);
	mainWnd.backgroundPanels = CreateSolidBrush(0xC0C0C0);
	mainWnd.panelColores = colorsWndCreate(hwnd, rcClient.right-200, 0, 200,rcClient.bottom);
	mainWnd.panelTool = toolWndCreate(hwnd, 0, 0, 20,rcClient.bottom, data);
	mainWnd.board = boardWndCreate(hwnd, 20, 0, rcClient.right-220,rcClient.bottom, data);
}

/**
Minerva only save in PNG like native format, but, can read BMP and PNG
*/
void mainWndArchivoGrabar(HWND hwnd, PDATA data, BOOL askByName){
	char fileName[300];
	FILECALLER caller;

	char *extension;

	if (!askByName && data->fileName[0]){
		extension = dataFileExtension(data->fileName);
		if (!extension || stricmp(extension,"png")){
			data->fileName[0] = 0;
		}
	}

	if (!data->fileName[0] || askByName){
		caller.filter = IMAGE_FILE_SAVER_FILTER;
		caller.hwndOwner = hwnd;
		caller.name = NULL;
		caller.directory = data->config->currentDir;
		if (!fileSaveFile(&caller, fileName)){
			return;
		}
		strcpy(data->fileName, fileName);
	}
	data->changed = FALSE;
	imageSaver(data->image, data->fileName, pngWrite);
}

void mainWndSaveChanges(HWND hwnd, PDATA data){
	if (data->changed){
		if (MessageBox(hwnd, "Guardar los cambios?", MESSAGE_TITLE, MB_YESNO)==IDYES){
			mainWndArchivoGrabar(hwnd, data, FALSE);
		}
		else{
			data->changed = FALSE;
		}
	}
}

void mainWndArchivoAbrir(HWND hwnd, PDATA data){
	char fileName[300];
	FILECALLER caller;

	mainWndSaveChanges(hwnd, data);
	if (data->changed){				
		return;
	}

	caller.filter = IMAGE_FILE_LOADER_FILTER;
	caller.hwndOwner = hwnd;
	caller.name = NULL;
	caller.directory = data->config->currentDir;
	if (fileLoadFile(&caller, fileName)){
		strcpy(data->fileName, fileName);
		IMAGE_CALLBACK reader = dataDetermineReader(fileName);
		if (reader!=NULL){
			PIMAGE image = imageLoader(fileName, reader);
			if (image==NULL){
				MessageBox(hwnd, "El formato no es soportado", MESSAGE_TITLE, MB_OK);
				return;
			}
			imageDelete(data->image);
			data->image = image;
			data->px = 0;
			data->py = 0;		
			InvalidateRect(mainWnd.board, NULL, FALSE);
			boardWndUpdateScrolls(mainWnd.board, data);
		}
	}
}

void mainWndArchivoNuevo(HWND hwnd, PDATA data){
	mainWndSaveChanges(hwnd, data);
	if (data->changed){				
		return;
	}
	data->fileName[0] = 0;
	OutputDebugString("TODO:File new");
}

void mainWndOnSize(HWND hwnd, LPARAM lParam){
	short dx = LOWORD(lParam);
	short dy = HIWORD(lParam);
	MoveWindow(mainWnd.panelTool, 0, 0, 20, dy, TRUE);
	MoveWindow(mainWnd.panelColores, dx-200, 0, 200, dy, TRUE);
	MoveWindow(mainWnd.board, 20, 0, dx-220, dy, TRUE);
}

void mainWndOnDestroy(HWND hwnd, PDATA data){
	RECT rc;
	GetWindowRect(hwnd, &rc);
	if (!IsZoomed(hwnd)){
		data->config->winpx = (short)rc.left;
		data->config->winpy = (short)rc.top;
		data->config->windx = (short)(rc.right - rc.left);
		data->config->windy = (short)(rc.bottom - rc.top);
	}
	data->config->isMaximized = IsZoomed(hwnd);
	DeleteObject(mainWnd.backgroundPanels);
}

void mainWndArchivoSalir(HWND hwnd, PDATA data){
	mainWndSaveChanges(hwnd, data);
	if (data->changed){				
		return;
	}
	PostQuitMessage(0);
}

BOOL CALLBACK mainWndAboutProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
	switch (message) 
    { 
        case WM_COMMAND: 
            switch (LOWORD(wParam)) 
            { 
                case IDOK:
                    EndDialog(hwnd, wParam); 
                    return TRUE; 
            }
    } 
	return FALSE;
}

void mainWndMenuCommand(HWND hwnd, UINT command, PDATA data){
	switch(command){
	case ID_ARCHIVO_NUEVO:
		mainWndArchivoNuevo(hwnd, data);
		break;
	case ID_ARCHIVO_ABRIR:
		mainWndArchivoAbrir(hwnd, data);
		break;
	case ID_ARCHIVO_GRABAR:
		mainWndArchivoGrabar(hwnd, data, FALSE);
		break;
	case ID_ARCHIVO_GRABARCOMO:
		mainWndArchivoGrabar(hwnd, data, TRUE);
		break;
	case ID_ARCHIVO_SALIR:
		mainWndArchivoSalir(hwnd, data);
		break;
	case ID_AYUDA_ACERCADEMINERVA:
		DialogBox((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDD_ABOUT), hwnd, mainWndAboutProc);
	}
}

void mainWndOnCommand(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, PDATA data){
	UINT source = HIWORD(wParam);
	UINT id = LOWORD(wParam);
	if (source==0){
		mainWndMenuCommand(hwnd, id, data);
	}
}

LRESULT CALLBACK mainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
	GET_DATA(PDATA);
	switch(message){	
	case WM_CLOSE:
		mainWndArchivoSalir(hwnd, data);
		break;
	case WM_CREATE:
		mainWndOnCreate(hwnd, data);
		break;
	case WM_DESTROY:
		mainWndOnDestroy(hwnd, data);
		break;
	case WM_SIZE:
		mainWndOnSize(hwnd, lParam);
		break;
	case WM_CTLCOLORSTATIC:
		return (LRESULT)mainWnd.backgroundPanels;
	case WM_COMMAND:
		mainWndOnCommand(hwnd, message, wParam, lParam, data);
		break;
    }
	return DefWindowProc(hwnd, message, wParam, lParam);
}

BOOL mainWndRegister(HINSTANCE instancia)
{
    if (!apiRegisterMainWnd(instancia, szClassName, mainWndProc, IDR_MAIN))
        return 0;
	colorsWndRegister(instancia);
	toolIniResources(instancia);
    return TRUE;
}



HWND mainWndCreate(HINSTANCE instancia, PDATA data)
{
    HWND hwnd;

    hwnd = CreateWindowEx (
           0,
           szClassName,
           "ageo|Minerva",
           WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
           CW_USEDEFAULT,
           CW_USEDEFAULT,
           544,
           375,
           HWND_DESKTOP,
           NULL,
           instancia,
           (LPVOID)data
           );
    ShowWindow (hwnd, data->config->isMaximized?SW_MAXIMIZE:SW_SHOW);
	boardWndUpdateScrolls(mainWnd.board, data);
    return hwnd;
}

int WINAPI WinMain (HINSTANCE instancia,
                    HINSTANCE prevInstancia,
                    LPSTR argumentos,
                    int nCmdShow)

{
    HWND hwnd;
    MSG messages;

	data = dataCreate();

	mainWndRegister(instancia);

	hwnd = mainWndCreate(instancia, data);
	while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }

	dataFreeData(data);	

	return messages.wParam;
}